package com.ccl.iot.privates;

import com.ccl.iot.publics.XCoreKernel;

public class SineWaveFilter {
	private int iMinInterval;
	private int iMaxInterval;
	private float iRange;
	private LinearFilter iFilter;
	
	private int iChanged = 0;
	private long iLastTime = 0;
	private boolean iRaising = false;
	private int iKeepStep = 0;
	private float iLastValue = 0;
	private float iMinValue = 0;
	private long iMinTime = 0;
	private float iMaxValue = 0;
	private long iMaxTime = 0;
	private int iBigChanged = 0;
	
	public SineWaveFilter(int aMinInterval, int aMaxInterval, float aRange, LinearFilter aFilter){
		iMaxInterval = aMaxInterval;
		iMinInterval = aMinInterval;
		iRange = aRange;
		iFilter = aFilter;
	}
	
	public void reset(){
		iBigChanged = 0;
		iKeepStep = 0;
	}
	
	public boolean put(float aValue){
		long tTime = XCoreKernel.SYSTICKCOUNT();
		
		if (iFilter != null){
			aValue = iFilter.put(aValue);
		}
		
		if (iChanged > 0){
			boolean tRaising = (aValue == iLastValue ? iRaising : (aValue > iLastValue));
			
			if (tRaising == iRaising){
				if (++iKeepStep == 1){
					if (tRaising){
						iMinValue = iLastValue;
						iMinTime = iLastTime;
					}else{
						iMaxValue = iLastValue;
						iMaxTime = iLastTime;
					}
				}else{
					if (tRaising){
						if (aValue > iMaxValue){
							iMaxValue = aValue;
							iMaxTime = tTime;
						}
					}else{
						if (aValue < iMinValue){
							iMinValue = aValue;
							iMinTime = tTime;
						}
					}
				}
			}else{
				boolean tBigChange = false;
				
				if (iRaising){
					if (iKeepStep > 6){
						long tInterval = XCoreKernel.GetTickInterval(iMinTime, iLastTime);
						
						if (tInterval >= iMinInterval && tInterval <= iMaxInterval){
							if (iLastValue - iMinValue >= iRange){
								tBigChange = true;
							}else{
								//Debugger.Warning(this.hashCode() + " failed when range=" + (iLastValue - iMinValue));
							}
						}else{
							//Debugger.Warning(this.hashCode() + " failed when interval=" +tInterval);
						}
					}
					
					iMinValue = iLastValue;
					iMinTime = iLastTime;
				}else{
					if (iKeepStep > 6){
						long tInterval = XCoreKernel.GetTickInterval(iMaxTime, iLastTime);
						
						if (tInterval >= iMinInterval && tInterval <= iMaxInterval){
							if (iMaxValue - iLastValue >= iRange){
								tBigChange = true;
							}else{
								//Debugger.Warning(this.hashCode() + " failed when range=" + (iMaxValue - iLastValue));
							}
						}else{
							//Debugger.Warning(this.hashCode() + " failed when interval=" +tInterval);
						}
					}
					
					iMaxValue = iLastValue;
					iMaxTime = iLastTime;
				}
				
				if (tBigChange){
					iBigChanged++;
				}else{
					iBigChanged = 0;
				}
				
				iRaising = tRaising;
				
				iKeepStep = 0;
			}
		}else{
			iKeepStep = 0;
			iBigChanged = 0;
		}
							
		if (iChanged < Integer.MAX_VALUE){
			iChanged++;
		}
		
		iLastValue = aValue;
		
		iLastTime = tTime;
		
		return (iBigChanged >= 3);
	}
}
